/*
 * Copyright (c) 2022 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "app_recovery.h"

#include "hilog_wrapper.h"
#include "js_runtime.h"
#include "js_runtime_utils.h"

#include "napi/native_api.h"
#include "napi/native_common.h"

namespace OHOS {
namespace AbilityRuntime {
namespace {
static napi_status SetEnumItem(napi_env env, napi_value object, const char* name, int32_t value)
{
    napi_status status;
    napi_value itemName;
    napi_value itemValue;
    NAPI_CALL_BASE(env, status = napi_create_string_utf8(env, name, NAPI_AUTO_LENGTH, &itemName), status);
    NAPI_CALL_BASE(env, status = napi_create_int32(env, value, &itemValue), status);
    NAPI_CALL_BASE(env, status = napi_set_property(env, object, itemName, itemValue), status);
    NAPI_CALL_BASE(env, status = napi_set_property(env, object, itemValue, itemName), status);
    return napi_ok;
}
}
AppRecovery::AppRecovery() : isEnable_(false), restartFlag_(RestartFlag::ALWAYS_RESTART),
    saveFlag_(SaveFlag::SAVE_WHEN_ERROR), saveMode_(SaveMode::SAVE_WITH_FILE)
{
    isEnable_ = true;
}

AppRecovery::~AppRecovery()
{
}

AppRecovery& AppRecovery::GetInstance()
{
    static AppRecovery instance;
    return instance;
}

void AppRecovery::EnableAppRecovery(RestartFlag restartFlag, SaveFlag saveFlag, SaveMode saveMode)
{
    isEnable_ = true;
    restartFlag_ = restartFlag;
    saveFlag_ = saveFlag;
    saveMode_ = saveMode;
}

bool AppRecovery::IsEnabled() const
{
    return isEnable_;
}

RestartFlag AppRecovery::GetRestartFlag() const
{
    return restartFlag_;
}

SaveFlag AppRecovery::GetSaveFlag() const
{
    return saveFlag_;
}

SaveMode AppRecovery::GetSaveMode() const
{
    return saveMode_;
}

static napi_value InitRestartFlagObject(napi_env env)
{
    napi_value object;
    NAPI_CALL(env, napi_create_object(env, &object));
    NAPI_CALL(env, SetEnumItem(env, object, "NONE", RestartFlag::ALWAYS_RESTART));
    NAPI_CALL(env, SetEnumItem(env, object, "CPP_CRASH_NO_RESTART", RestartFlag::CPP_CRASH_NO_RESTART));
    NAPI_CALL(env, SetEnumItem(env, object, "JS_CRASH_NO_RESTART", RestartFlag::JS_CRASH_NO_RESTART));
    NAPI_CALL(env, SetEnumItem(env, object, "APP_FREEZE_NO_RESTART", RestartFlag::APP_FREEZE_NO_RESTART));
    return object;
}

static napi_value InitSaveFlagObject(napi_env env)
{
    napi_value object;
    NAPI_CALL(env, napi_create_object(env, &object));
    NAPI_CALL(env, SetEnumItem(env, object, "NONE", SaveFlag::NO_SAVE));
    NAPI_CALL(env, SetEnumItem(env, object, "SAVE_WHEN_ERROR", SaveFlag::SAVE_WHEN_ERROR));
    NAPI_CALL(env, SetEnumItem(env, object, "SAVE_WHEN_BACKGROUND", SaveFlag::SAVE_WHEN_BACKGROUND));
    return object;
}

static napi_value InitSaveModeObject(napi_env env)
{
    napi_value object;
    NAPI_CALL(env, napi_create_object(env, &object));
    NAPI_CALL(env, SetEnumItem(env, object, "SAVE_WITH_FILE", SaveMode::SAVE_WITH_FILE));
    NAPI_CALL(env, SetEnumItem(env, object, "SAVE_WITH_DB", SaveMode::SAVE_WITH_DB));
    NAPI_CALL(env, SetEnumItem(env, object, "SAVE_WITH_SHARED_MEMORY", SaveMode::SAVE_WITH_SHARED_MEMORY));
    return object;
}
static napi_value EnableAppRecovery(napi_env env, napi_callback_info info)
{
    HILOG_INFO("AppRecovery Init.");
    return nullptr;
}

napi_value InitAppRecoveryModule(napi_env env, napi_value exports)
{
    HILOG_INFO("AppRecovery Init.");
    if (env == nullptr || exports == nullptr) {
        HILOG_INFO("engine or exportObj null");
        return nullptr;
    }

    napi_value restartFlag = InitRestartFlagObject(env);
    if (restartFlag == nullptr) {
        HILOG_ERROR("failed to create restart flag object");
        return nullptr;
    }

    napi_value saveFlag = InitSaveFlagObject(env);
    if (saveFlag == nullptr) {
        HILOG_ERROR("failed to create save flag object");
        return nullptr;
    }

    napi_value saveMode = InitSaveModeObject(env);
    if (saveMode == nullptr) {
        HILOG_ERROR("failed to create save mode object");
        return nullptr;
    }

    napi_property_descriptor enumObjs[] = {
        DECLARE_NAPI_PROPERTY("RestartFlag", restartFlag),
        DECLARE_NAPI_PROPERTY("SaveFlag", saveFlag),
        DECLARE_NAPI_PROPERTY("SaveMode", saveMode),
    };

    napi_status status = napi_define_properties(env, exports, sizeof(enumObjs) / sizeof(enumObjs[0]), enumObjs);
    if (status != napi_ok) {
        HILOG_ERROR("failed to define properties for exports");
        return nullptr;
    }

    HILOG_INFO("AppRecovery called");
    napi_property_descriptor func[] = {
        DECLARE_NAPI_FUNCTION("enableAppRecovery", EnableAppRecovery),
    };
    NAPI_CALL(env, napi_define_properties(env, exports, sizeof(func) / sizeof(func[0]), func));
    return exports;
}
}  // namespace AbilityRuntime
}  // namespace OHOS
